/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pnt.server;

import java.net.*;
import java.util.Vector;
import java.util.logging.Logger;

/**
 * Cycles through TCP connections, and handles UDP datapackets.
 * 
 * @author andrew
 */
public class ConnectionManager {
    
    @SuppressWarnings("unused")
	private static Logger logger = Logger.getLogger("pnt.server"); 
    
    private Vector<DatagramPair> messageQueue;
    private boolean running = false;
    
    // TODO: make assistedConnections a 2-d hashtable?
    private Vector<Connection> autonomousConnections;
    private Vector<UDPConnection> assistedConnections;
    
    public ConnectionManager(){
        messageQueue = new Vector<DatagramPair>();
        autonomousConnections = new Vector<Connection>();
        assistedConnections = new Vector<UDPConnection>();
    }
    
    public void addConnection(Connection c){
        synchronized(autonomousConnections){
            autonomousConnections.add(c);
        }
    }
    
    public void processMessage(DatagramPacket dp, DatagramSocket ds){
        synchronized(messageQueue){
            messageQueue.add(new DatagramPair(dp,ds));
        }
    }
    
    public void run(){
        
        running = true;
        
        while(running){
            synchronized(autonomousConnections){
                // process TCP connections
                for(Connection c : autonomousConnections){
                    if( c.attentionNeeded() > 0 ) c.run();
                    else if( c.attentionNeeded() < 0) autonomousConnections.remove(c); // Does this work?
                }
            }
        
            // process UDP "connections"
            synchronized(messageQueue){
                while( !messageQueue.isEmpty() ){
                    DatagramPair d2 = messageQueue.remove(0);
                    DatagramPacket dp = d2.dp;
                    DatagramSocket ds = d2.ds;
                    UDPConnection c = getConnection(dp);
                    if(c == null)
                        c = new UDPConnection(dp, ds);
                    c.addMessage(dp);
                    c.run();
                }
            }
        }
        
    }

    public void stop() {
        running = false;
    }

    // Retrieves the connection for the given packet
    private UDPConnection getConnection(DatagramPacket dp) {
        // TODO: change this so it inspects the message's contents?
        for(UDPConnection c : assistedConnections){
            if( c.getClientPort() == dp.getPort() &&
                c.getClientAddress().getHostAddress().hashCode() == dp.getAddress().hashCode())
                return c;
        }
        return null;
    }

    // Sort of a hack, but not really
    private class DatagramPair{
        private DatagramPacket dp;
        private DatagramSocket ds;
        private DatagramPair(DatagramPacket dp, DatagramSocket ds){
            this.dp = dp;
            this.ds = ds;
        }
    }
    
}
